library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity TDMOIP_TOP is
	GENERIC
   (
	   LED_ON :  std_logic  :=  '1';
	   LED_OFF   :  std_logic  :=  '0';
	   RST50HZ_CNT   :  integer := 15
	 );--�������������һ�в��ܼӷֺţ���Ȼ����ᱨ��

    Port (
		--------clock---------------
        OSC65M: in std_logic;
        OSC25M: in std_logic;
        CLK25M_CPU: out std_logic;
        CLK25M_A: out std_logic;
           
		   
 	   --------reset -------------
        resetn : out std_logic;
		   
 	   --------fsmc nand -------------  
		fsmc_NWE : in std_logic;   -- write en
		fsmc_NOE : in std_logic;   -- read en
		fsmc_A16_CLE : in std_logic; -- cmd lock
		fsmc_A17_ALE : in std_logic; -- addr lock 
		fsmc_NWAIT : out std_logic; -- BUSY 
		fsmc_addrData : inout std_logic_vector(7 downto 0);

		
 	   --------TTL232\phone8 -------------
	   TTL_RX1 : in std_logic;
	   TTL_TX1 : out std_logic;
	   TTL_RCLK1 : out std_logic;
	   TTL_TCLK1 : out std_logic;

 	   --------fifo rx -------------
	   FIFO_RX_AlmostFull : out std_logic;
	   FIFO_TX_AlmostEmpty : out std_logic;

	   

 	   --------LED -------------
        LED1 : out std_logic;
        LED2 : out std_logic;
        LED3 : out std_logic;
        LED4 : out std_logic
	);

end TDMOIP_TOP;



architecture Behavioral of TDMOIP_TOP is

	component fifo_dc
        port (
			Data : in std_logic_vector(7 downto 0); 
        	WrClock: in std_logic; 
			RdClock: in std_logic; 
			WrEn: in std_logic; 
        	RdEn: in std_logic; 
			Reset: in std_logic; 
			RPReset: in std_logic; 
        	Q : out std_logic_vector(7 downto 0); 
			Empty: out std_logic; 
        	Full: out std_logic; 
			AlmostEmpty: out std_logic; 
        	AlmostFull: out std_logic
    	);
    end component;

	component fifo_dc2
        port (
			Data : in std_logic_vector(7 downto 0); 
        	WrClock: in std_logic; 
			RdClock: in std_logic; 
			WrEn: in std_logic; 
        	RdEn: in std_logic; 
			Reset: in std_logic; 
			RPReset: in std_logic; 
        	Q : out std_logic_vector(7 downto 0); 
			Empty: out std_logic; 
        	Full: out std_logic; 
			AlmostEmpty: out std_logic; 
        	AlmostFull: out std_logic
    	);
    end component;

	signal CLK50HZ,CLK2M,CLK25M,SYSRESETN : std_logic;
	SIGNAL RSTCNT:STD_LOGIC_VECTOR(15 DOWNTO 0);
	SIGNAL RSTCNT1:STD_LOGIC_VECTOR(5 DOWNTO 0);
    signal divClk25M : std_logic_vector(23 downto 0);
    signal div2Clk25M : std_logic_vector(3 downto 0);
    signal divClk65M : std_logic_vector(7 downto 0);
	
	-- test para -- 
    signal fifo_TX_Testdata : std_logic_vector(7 downto 0):=  "11111111";
	signal err1_flag, err2_flag, err3_flag,err4_flag: std_logic_vector(9 downto 0);
	signal LEDTEST : std_logic_vector(3 downto 0):=  "1111";

	--fsmc para--
	signal fsmc_NWE_up,fsmc_NOE_up : std_logic;
    signal fsmc_addr,fsmc_Raddr ,fsmc_Waddr : std_logic_vector(1 downto 0):=  "00";
    signal fsmc_reg0data : std_logic_vector(7 downto 0):=  "10101010"; 
    signal fsmc_reg1data : std_logic_vector(7 downto 0):=  "00001010";
    signal fsmc_reg2data : std_logic_vector(7 downto 0):=  "00001011";
    signal fsmc_reg3data : std_logic_vector(7 downto 0):=  "01010101";

	--fifo para--
	signal fifo_RX_reset,  fifo_TX_reset: std_logic;
    signal fifo_cnt : std_logic_vector(2 downto 0);
	--fifo RX para rcv TTL232--
	signal fifo_RX_WE,fifo_RX_RE, fifo_RX_Empty, fifo_RX_Full, fifo_RX_AlmostEmpty : std_logic;
	signal fifo_RX_WrClock,fifo_RX_RdClock: std_logic;
    signal fifo_RX_indata : std_logic_vector(7 downto 0);
    signal fifo_RX_outdata : std_logic_vector(7 downto 0):=  "11111111";

	--fifo TX para send TTL232--
	signal fifo_TX_WE,fifo_TX_RE,fifo_TX_Empty, fifo_TX_Full,  fifo_TX_AlmostFull : std_logic;
	signal fifo_TX_WrClock,fifo_TX_RdClock: std_logic;
    signal fifo_TX_indata : std_logic_vector(7 downto 0);
    signal fifo_TX_outdata : std_logic_vector(7 downto 0);
    signal fifo_TX_Tlldata : std_logic_vector(7 downto 0):=  "11111111";
	
	begin
	
	CLK25M  <= OSC25M;
	CLK25M_CPU <= OSC25M;
	CLK25M_A <= OSC25M;
	--------------------fifo------------------------------
	fifo_RX_reset<='1' when RSTCNT1 < RST50HZ_CNT or fsmc_reg0data /= "01010101" else '0'; -- 1 to 0
	TTL232_RX : fifo_dc port map (
			Data => fifo_RX_indata, 
			WrClock => fifo_RX_WrClock, 
			RdClock => fifo_RX_RdClock, 
            WrEn => fifo_RX_WE, 
			RdEn => fifo_RX_RE, 
			Reset => fifo_RX_reset, 
			RPReset => fifo_RX_reset, 
            Q => fifo_RX_outdata, 
			Empty =>fifo_RX_Empty, 
			Full => fifo_RX_Full, 
			AlmostEmpty => fifo_RX_AlmostEmpty, 
            AlmostFull => FIFO_RX_AlmostFull
        );
	
	fifo_TX_reset<='1' when RSTCNT1 < RST50HZ_CNT  else '0'; -- 1 to 0
	TTL232_TX : fifo_dc2 port map (
			Data => fifo_TX_indata, 
			WrClock => fifo_TX_WrClock, 
			RdClock => fifo_TX_RdClock, 
            WrEn => fifo_TX_WE, 
			RdEn => fifo_TX_RE, 
			Reset => fifo_TX_reset, 
			RPReset => fifo_TX_reset, 
            Q => fifo_TX_outdata, 
			Empty =>fifo_TX_Empty, 
			Full => fifo_TX_Full, 
			AlmostEmpty => FIFO_TX_AlmostEmpty, 
            AlmostFull => fifo_TX_AlmostFull
        );
	-- fifo_RX_WrClock <= CLK2M;
	-- fifo_TX_RdClock <= CLK2M;
	
	fifo_RX_WrClock <=  '1' when fifo_cnt = "000" else '0';
	fifo_RX_WE <= not fifo_RX_reset; 

	fifo_TX_RdClock <=  '1' when fifo_cnt = "000" else '0';
	fifo_TX_RE <= not fifo_RX_reset; 
	TTL_RCLK1 <= CLK2M;
	TTL_TCLK1 <= NOT CLK2M;
	PROCESS(CLK2M, fifo_RX_reset)
		BEGIN
		if(fifo_RX_reset = '1')then fifo_cnt <= "000"; fifo_RX_indata<="00000000";TTL_TX1 <= '1';--fifo_RX_WE <= '0';
		elsif(CLK2M'event and CLK2M='1') then

			if(fifo_RX_Empty = '1') then err1_flag <= err1_flag + 1;
			end if;
			-- if(fifo_RX_Full = '1') then err2_flag <= err2_flag + 1;
			-- end if;
			-- if(fifo_TX_Empty = '1') then err3_flag <= err3_flag + 1;
			-- end if;
			if(fifo_TX_Full = '1') then err4_flag <= err4_flag + 1;
			end if;
			
			 
			--get ttl_rx,write to fifo
			fifo_cnt <= fifo_cnt + '1';
			fifo_RX_indata(0) <= TTL_RX1;
			fifo_RX_indata(7 DOWNTO 1) <= fifo_RX_indata(6 DOWNTO 0);
			--测试误码率使用
			-- if(fifo_cnt = "000") then fifo_RX_indata <= fifo_RX_indata + '1';
			-- end if;

			--get fifo, to ttl_tx
			TTL_TX1 <= fifo_TX_Tlldata(7);
			case fifo_cnt is
				when "000" => 
					if(fifo_TX_Empty = '1')then fifo_TX_Tlldata <= "11111111";LEDTEST(3) <= not LEDTEST(3);
					else fifo_TX_Tlldata <= fifo_TX_outdata;
					end if;
					fifo_TX_Testdata <= fifo_TX_outdata;
					if(fifo_TX_Testdata + '1' = fifo_TX_outdata)then NULL;
					else
						err2_flag <= err2_flag + '1';
					end if;
				when others => fifo_TX_Tlldata(7 DOWNTO 1) <= fifo_TX_Tlldata(6 DOWNTO 0);
			end case;
		end if;
	END PROCESS;

	fifo_RX_RdClock <= not fsmc_NOE;
	fifo_RX_RE <= not fifo_RX_reset; 

	fifo_TX_WrClock <= fsmc_NWE ;
	fifo_TX_WE <= '1' when fsmc_A16_CLE='0' and fsmc_A17_ALE= '0' and fifo_TX_reset= '0' else '0';

	-- 使用下面115200波特率乱码
	-- fifo_TX_WrClock <= fsmc_NWE when fsmc_A17_ALE= '0' else '1';
	-- fifo_TX_WE <= not fifo_TX_reset ;
	-- 收发fifo自环
	-- fifo_TX_indata <= fifo_RX_outdata;
	-- fifo_TX_WrClock <=  fsmc_NOE;
	-- fifo_TX_WE <= not fifo_RX_reset; 
	--------------------CLK2M,CLK50HZ------------------------------
	PROCESS(CLK25M)
		BEGIN
		if(CLK25M'event and CLK25M='1') then
			divClk25M <= divClk25M + '1';
		end if;
	END PROCESS;
	CLK50HZ  <= divClk25M(18);
	
	-- CLK2M  <= divClk25M(2);
	PROCESS(OSC65M)
		BEGIN
		if(OSC65M'event and OSC65M='1') then
			divClk65M <= divClk65M + '1';
		end if;
	END PROCESS;
	CLK2M  <= divClk65M(4);
	
	----------------genarate RESETN 20*RST50HZ_CNT ms--------------------------
	PROCESS(CLK50HZ)
		BEGIN
		if(CLK50HZ'event and CLK50HZ='1') then
			IF(RSTCNT1 < RST50HZ_CNT) THEN RSTCNT1<=RSTCNT1+'1';
			END IF;
		end if;
	end process;
	resetn<='0' when RSTCNT1 < RST50HZ_CNT else '1';
	

	----------------FPGA ready--------------------------
	PROCESS(CLK25M)
	BEGIN
	if(CLK25M'event and CLK25M='1') then
    	IF(RSTCNT/="1010101010101010") THEN RSTCNT<=RSTCNT+'1';
    	END IF;
	end if;
	END PROCESS;
	SYSRESETN<='0' when RSTCNT/="1010101010101010" else '1';
	
	----------------FPGA fsmc--------------------------
	fsmc_NWAIT <= SYSRESETN;
	PROCESS(OSC65M,SYSRESETN,fsmc_A16_CLE,fsmc_A17_ALE,fsmc_NWE,fsmc_NOE)
	BEGIN
	if(SYSRESETN='0') then fsmc_addr<="00";
	elsif(fsmc_A16_CLE='0') then
		-- get addr -- 
    	IF(fsmc_A17_ALE= '1') then
			fsmc_addrData<="ZZZZZZZZ";
			if(fsmc_NWE'event and fsmc_NWE='1') then
				fsmc_addr <= fsmc_addrData(1 downto 0);
				fsmc_Raddr <= fsmc_addrData(1 downto 0);
				fsmc_Waddr <= fsmc_addrData(1 downto 0);
			END IF;
		else 
			-- write data -- 
			if(fsmc_NWE'event and fsmc_NWE='1') then
				-- fifo_TX_indata <= fsmc_addrData;
				case fsmc_Waddr is
					when "00" => fsmc_reg0data <= fsmc_addrData;
					-- when "01" => fsmc_reg1data <= fsmc_addrData;
					-- when "10" => fsmc_reg2data <= fsmc_addrData;
					-- when "11" => fsmc_reg3data <= fsmc_addrData;
					when others => fifo_TX_indata <= fsmc_addrData;
				end case;
				if(fsmc_Waddr = "00")then NULL;
				elsif(fifo_TX_indata + '1' = fsmc_addrData)then NULL;
				else
					err3_flag <= err3_flag + '1';
				end if;
			END IF;
			-- read data -- 
			if(fsmc_NOE'event and fsmc_NOE='0') then
				fsmc_addrData <= fifo_RX_outdata;
				-- case fsmc_Raddr is
				-- 	when "00" => fsmc_addrData <= fsmc_reg0data;
				-- 	when "01" => fsmc_addrData <= fsmc_reg1data;
				-- 	when "10" => fsmc_addrData <= fsmc_reg2data;
				-- 	when "11" => fsmc_addrData <= fsmc_reg3data;
				-- 	when others => fsmc_addrData <= "11001100";
				-- end case;
				-- 	fsmc_Raddr <= fsmc_Raddr +'1';
				LEDTEST(0) <= not LEDTEST(0);
				
			END IF;
		end if;
	end if; 
	END PROCESS;
	
	---------------- LED ctr--------------------------
	LED1  <= err1_flag(6);--LEDTEST(0);
	LED2  <= err2_flag(6);--LEDTEST(1);
	LED3  <= err3_flag(6);--LEDTEST(2);
	LED4  <= err4_flag(6);--LEDTEST(3);
end Behavioral;